package com.luhongzhe.gameview;

import java.util.Date;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.MotionEvent;

import com.luhongzhe.Luhongzhe;
import com.luhongzhe.R;
import com.luhongzhe.tool.PathParser;
import com.luhongzhe.tool.PhysicalTool;

import data.ObjectDrawable;

/**
 * @author 	luhongzhe
 * @email  	azhe0660@gmail.com
 * @date   	2011-11-1
 */

public class FallingBoxsView extends CommonGameView
{
	private FallingBox[] mFallingBoxs;
	private ObjectDrawable car;
	private Bitmap bmpLand;
	
	public FallingBoxsView(Context context, GameViewHolder holder)
	{
		super(context, holder);
	}
	
	@Override
	protected void drawGame(Canvas canvas)
	{
		for (int i = 0; i < mFallingBoxs.length; i++)
		{
			mFallingBoxs[i].draw(canvas);
		}
		
		canvas.drawBitmap(bmpLand, 0, 0, null);
	}
	
	@Override
	protected void onTouchDown(MotionEvent event)
	{
		super.onTouchDown(event);
		for (int i = 0; i < mFallingBoxs.length; i++)
		{
			 mFallingBoxs[i].hasCut = false;
		}
	}
	
	@Override
	protected void onTouchMove(MotionEvent event)
	{
		float x = event.getX();
		float y = event.getY();
		if (!hasSucceed)
    	{
			int cutCount = 0;
			for (int i = 0; i < mFallingBoxs.length; i++)
			{
				if (mFallingBoxs[i].getBounds().contains((int)x, (int)y))
				{
					float rotation = (float)(Math.atan2(y - mY, x - mX) * 180 / Math.PI); 
		    		Log.d(Luhongzhe.Tag, "rotation is " + rotation);
		    		rotation = (rotation + 360) % 360;
		    		if (rotation < 45 || rotation > 315)
		    			rotation = 0;
		    		else if (rotation >= 45 && rotation < 135)
		    			rotation = 90;
		    		else if (rotation >= 135 && rotation <= 225)
		    			rotation = 180;
		    		else rotation = 270;
		    		Log.d(Luhongzhe.Tag, "rotation is " + rotation);
		    		
		    		mFallingBoxs[i].cut(rotation);
		    		cutCount ++;
				}
			}
			
			if (cutCount == mFallingBoxs.length)
			{
				onSucceed();
				mX = x;
	    		mY = y;
				return;
			}
    	}
		
		super.onTouchMove(event);
	}
	
	@Override
	protected void init()
	{
		int fallingX = this.getMeasuredWidth() / 10;
		int boxSpace = (int)(((this.getMeasuredWidth() * 0.8) - 3 * FallingBox.DEFAULTSIZE) / 2);
		float[] gravityAs = new float[]{0.0002f, 0.0005f, 0.0003f};
		
		mFallingBoxs = new FallingBox[3];
		for (int i = 0; i < mFallingBoxs.length; i++)
		{
			mFallingBoxs[i] = new FallingBox();
			mFallingBoxs[i].fallingX = fallingX;
			fallingX += boxSpace;
			mFallingBoxs[i].gravityA = gravityAs[i];
		}
		
		car = new ObjectDrawable();
		car.setPath(PathParser.getCar(), 200, 200);
		
		bmpLand = BitmapFactory.decodeResource(getResources(), R.drawable.land);
		
		super.init();
	}
	
	class FallingBox extends Drawable
	{
		private static final int DEFAULTSIZE = 50;
		
		private boolean hasCut;
		private long cutTime;
		private int cutX, cutY;
		private float hitRotation;
		
		private long beginTime;
		
		//掉落的x坐标
		private int fallingX;
		
		//重力加速度
		private float gravityA = PhysicalTool.gravityA;
		
		public FallingBox()
		{
			this.setBounds(0, 0, DEFAULTSIZE, DEFAULTSIZE);
			beginTime = new Date().getTime();
		}
		
		public void move(int x, int y)
		{
			this.setBounds(x, y, x + DEFAULTSIZE, y + DEFAULTSIZE);
		}
		
		public void cut(float hitRotation)
		{
			if (!hasCut)
			{
				cutTime = getTime();
				this.cutX = FallingBox.this.getBounds().left;
				this.cutY = FallingBox.this.getBounds().top;
				this.hitRotation = hitRotation;
				hasCut = true;
			}
		}
		
		@Override
		public void draw(Canvas canvas)
		{
			if (!hasCut)
			{
				int time = (int)getTime();
//				time %= gravityTool.getCycleTime();
				time %= PhysicalTool.getTime(FallingBoxsView.this.getMeasuredHeight() + DEFAULTSIZE * 2,
						0, gravityA);
				
//				int offset = (int)gravityTool.getOffset(time);
				int offset = (int)PhysicalTool.getDistance(0, gravityA, time);
				
				this.move(fallingX, offset - DEFAULTSIZE);
				
				canvas.drawRect(this.getBounds(), defaultPaint);
			}
			else
			{
				this.setBounds(canvas.getClipBounds());
				int time = (int)(getTime() - cutTime);
				
				float hitAcceleration = 0.1f;
				
//				float hitRotation = 270;
				
				//child1
				float childHitRotation = hitRotation - 45;
				
				int offsetY = (int)PhysicalTool.getDistance(hitAcceleration * (float)Math.sin(childHitRotation * Math.PI / 180) , gravityA, time);
				int offsetX = (int)(time * hitAcceleration * Math.cos(childHitRotation * Math.PI / 180));
				
				int clockwise = -1;
				float rotation = hitRotation + clockwise * (time * 90 / 1000) % 360;
				
				Rect bound = new Rect(cutX + offsetX, offsetY + cutY, cutX + offsetX + DEFAULTSIZE, offsetY + cutY + DEFAULTSIZE / 2);
				canvas.save();
				canvas.rotate(rotation, bound.centerX(), bound.centerY());
				canvas.drawRect(bound, defaultPaint);
				canvas.restore();
				
				//child2
				childHitRotation = hitRotation + 45;
				offsetX = (int)(time * hitAcceleration * Math.cos(childHitRotation * Math.PI / 180));
				offsetY = (int)PhysicalTool.getDistance(hitAcceleration * (float)Math.sin(childHitRotation * Math.PI / 180) , gravityA, time);
				
				clockwise = 1;
				rotation = hitRotation + clockwise * (time * 90 / 1000) % 360;
				
				bound = new Rect(cutX + offsetX, offsetY + cutY, cutX + offsetX + DEFAULTSIZE, offsetY + cutY + DEFAULTSIZE / 2);
				canvas.save();
				canvas.rotate(rotation, bound.centerX(), bound.centerY());
				canvas.drawRect(bound, defaultPaint);
				canvas.restore();
			}
		}

		@Override
		public void setAlpha(int alpha) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void setColorFilter(ColorFilter cf) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public int getOpacity() {
			// TODO Auto-generated method stub
			return 0;
		}
		
		private long getTime()
		{
			return new Date().getTime() - beginTime;
		}
		
	}

}
